<template>
  <el-form
    ref="formRef"
    :model="modelValue"
    :rules
    label-width="auto"
    label-position="right"
  >
    <el-row :gutter="16">
      <el-col v-for="item in items" :span="item.span ?? 24">
        <el-form-item :label="item.label" :prop="item.prop">
          <slot :name="item.prop">
            <component
              :is="getComponent(item.type)"
              v-bind="getProps(item)"
              v-model="modelValue[item.prop]"
            ></component>
          </slot>
        </el-form-item>
      </el-col>
    </el-row>
  </el-form>
</template>

<script setup lang="ts">
import { ElInput, ElInputNumber, ElSelectV2 } from 'element-plus'

const props = defineProps(['formItems', 'rules'])

const items = computed(() => {
  return props.formItems.filter((item: any) => !item.hidden)
})

const modelValue = defineModel({
  type: Object,
  default: () => ({})
})

const componentMap = {
  input: ElInput,
  number: ElInputNumber,
  select: ElSelectV2
} as any

const getComponent = (type: any = 'input') => {
  if (typeof type !== 'string') return type
  return componentMap[type]
}

const formInstance = useTemplateRef('formRef')

defineExpose({
  validate(...args: any[]) {
    return formInstance.value?.validate(...args)
  }
})

const rootProps = ['label', 'prop', 'type']

const omit = (obj: any, keys: any) => {
  const ret = {} as any
  Object.keys(obj).forEach(key => {
    if (!keys.includes(key)) {
      ret[key] = obj[key]
    }
  })
  return ret
}

const getProps = (item: { props?: any }) => {
  if (item.props) return item.props
  return omit(item, rootProps)
}
</script>

<style scoped lang="scss"></style>
